home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 25 / CU Amiga Magazine's Super CD-ROM 25 (1998)(EMAP Images)(GB)(Track 1 of 2)[!][issue 1998-08].iso / CUCD / Magazine / C_Tutorial / Part-13 / PatchLib / source / Patch_Lowlevel.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-08-26  |  16.8 KB  |  768 lines

  1. /*
  2. **    patch.library
  3. **
  4. **    Copyright © 1993-1997 by Stefan Fuchs
  5. **        Freely distributable.
  6. */
  7.  
  8. #ifndef _PATCH_INCLUDES_H
  9. #include "patch_includes.h"
  10. #endif
  11.  
  12. #define INSTR_JMP    0x4ef9
  13. #define INSTR_JSR    0x4eb9
  14.  
  15.  
  16. /****i* patch.library/ReturnD1 ***************************************
  17. *
  18. *   NAME
  19. *        ReturnD1 -- Set register d1 to a specific value. 
  20. *
  21. *   SYNOPSIS
  22. *        ReturnD1( value )
  23. *
  24. *        ReturnD1( ULONG );
  25. *
  26. *   FUNCTION
  27. *        Set register d1 to a specific value.
  28. *
  29. *   INPUTS
  30. *        value = value to be placed in register d1.
  31. *
  32. *   NOTES
  33. *        Hopefully this function is not removed by the compiler.
  34. *
  35. ******************************************************************************
  36. *
  37. */
  38. void ASMFUNC ReturnD1( REGD1 ULONG result GNUC_REGD1)
  39. {
  40. }
  41.  
  42.  
  43. /****i* patch.library/GetNumberOfNodes ***************************************
  44. *
  45. *   NAME
  46. *        GetNumberOfNodes -- Return the number of nodes in a List.
  47. *
  48. *   SYNOPSIS
  49. *        Number = GetNumberOfNodes( list )
  50. *
  51. *        ULONG GetNumberOfNodes( struct List *);
  52. *
  53. *   FUNCTION
  54. *        Return the number of nodes in an exec list.
  55. *
  56. *   INPUTS
  57. *        list = pointer to a List structure
  58. *
  59. *   RESULT
  60. *        Number = Number of nodes in the given exec list.
  61. *
  62. *   BUGS
  63. *
  64. ******************************************************************************
  65. *
  66. */
  67.  
  68. LONG GetNumberOfNodes(struct List *header)
  69. {
  70. LONG counter = - 2;
  71.  
  72.     do
  73.     {
  74.         counter++;
  75.         header = (struct List *)header->lh_Head;
  76.     }
  77.     while(header);
  78.     return(counter);
  79. }
  80.  
  81.  
  82. /****i* patch.library/ADeleteMyListNode ***************************************
  83. *
  84. *   NAME
  85. *        ADeleteMyListNode -- Remove and deallocate node.
  86. *
  87. *   SYNOPSIS
  88. *        ADeleteMyListNode( node )
  89. *
  90. *        ADeleteMyListNode( struct Node *);
  91. *
  92. *   FUNCTION
  93. *        Remove and deallocate exec node. This node must have been created by one
  94. *        of the ACreateMyListNode* () functions.
  95. *
  96. *   INPUTS
  97. *        node = pointer to a node structure or NULL for no action
  98. *
  99. *   RESULT
  100. *
  101. *   NOTES
  102. *
  103. *   BUGS
  104. *
  105. *   SEE ALSO
  106. *        ACreateMyListNode(), AFreemem()
  107. *
  108. ******************************************************************************
  109. *
  110. */
  111.  
  112.  
  113. void ADeleteMyListNode( struct Node *node)
  114. {
  115.     if(node)
  116.     {
  117.         Remove(node);
  118.         AFreemem(node);
  119.     }
  120. }
  121.  
  122.  
  123. /****i* patch.library/ACreateMyListNodeNamed ***************************************
  124. *
  125. *   NAME
  126. *        ACreateMyListNodeNamed -- Create and add a named node.
  127. *
  128. *   SYNOPSIS
  129. *        node = ACreateMyListNodeNamed( list, length, name )
  130. *
  131. *        struct Node *ACreateMyListNodeNamed( struct List *, ULONG, STRPTR );
  132. *
  133. *   FUNCTION
  134. *        Create a node structure of the given size and name and add it to
  135. *        the given list.
  136. *        This node can be removed by a call to ADeleteMyListNode().
  137. *
  138. *   INPUTS
  139. *        list = pointer to a list structure
  140. *        length = size of node in bytes
  141. *        name = name of the node to add or NULL, for an unnamed node
  142. *
  143. *   RESULT
  144. *        node = pointer to the newly created node structure or NULL on failure
  145. *
  146. *   NOTES
  147. *
  148. *   BUGS
  149. *
  150. *   SEE ALSO
  151. *        ACreateMyListNode(), ADeleteMyListNode(), BAllocmem()
  152. *
  153. ******************************************************************************
  154. *
  155. */
  156.  
  157. struct Node *ACreateMyListNodeNamed(struct List *header, ULONG length, STRPTR string)
  158. {
  159. struct Node *pointer;
  160.     if(string)
  161.     {
  162.         pointer = (struct Node *)BAllocmem( length + strlen( string) + 1, MEMF_CLEAR | MEMF_PUBLIC);
  163.         if(pointer)
  164.         {
  165.             pointer->ln_Name = strcpy((char *) ((ULONG)pointer+length), string);
  166.             AddTail( header, pointer);
  167.         }
  168.     }
  169.     else
  170.     {
  171.         pointer = ACreateMyListNode( header, length);
  172.     }
  173.     return(pointer);
  174. }
  175.  
  176.  
  177. /****i* patch.library/ACreateMyListNode ***************************************
  178. *
  179. *   NAME
  180. *        ACreateMyListNode -- Create and add a node.
  181. *
  182. *   SYNOPSIS
  183. *        node = ACreateMyListNode( list, length )
  184. *
  185. *        struct Node *ACreateMyListNode( struct List *, ULONG);
  186. *
  187. *   FUNCTION
  188. *        Create a node structure of the given size and add it to
  189. *        the given list.
  190. *        This node can be removed by a call to ADeleteMyListNode().
  191. *
  192. *   INPUTS
  193. *        list = pointer to a list structure or NULL for no action
  194. *        length = size of node in bytes
  195. *
  196. *   RESULT
  197. *        node = pointer to the newly created node structure or NULL on failure
  198. *
  199. *   NOTES
  200. *
  201. *   BUGS
  202. *
  203. *   SEE ALSO
  204. *        ACreateMyListNode(), ADeleteMyListNode(), BAllocmem()
  205. *
  206. ******************************************************************************
  207. *
  208. */
  209.  
  210. struct Node *ACreateMyListNode(struct List *header, ULONG length)
  211. {
  212. struct Node *pointer = 0;
  213.     if(header)
  214.     {
  215.         pointer = (struct Node *)BAllocmem( length, MEMF_CLEAR | MEMF_PUBLIC);
  216.         if(pointer) AddTail( header, pointer);
  217.     }
  218.     return(pointer);
  219. }
  220.  
  221.  
  222. /****i* patch.library/ACreateMyListNodeNamedPri ***************************************
  223. *
  224. *   NAME
  225. *        ACreateMyListNodeNamedPri -- Create and add a named node with priority.
  226. *
  227. *   SYNOPSIS
  228. *        node = ACreateMyListNodeNamedPri( list, length, name, priority )
  229. *
  230. *        struct Node *ACreateMyListNodeNamedPri( struct List *, ULONG, STRPTR, BYTE );
  231. *
  232. *   FUNCTION
  233. *        Create a node structure of the given size and name and add it to
  234. *        the given list with the given priority.
  235. *        This node can be removed by a call to ADeleteMyListNode().
  236. *
  237. *   INPUTS
  238. *        list = pointer to a list structure
  239. *        length = size of node in bytes
  240. *        name = name of the node to add or NULL, for an unnamed node
  241. *        priority = position at which the node is to be added to the list
  242. *
  243. *   RESULT
  244. *        node = pointer to the newly created node structure or NULL on failure
  245. *
  246. *   NOTES
  247. *
  248. *   BUGS
  249. *
  250. *   SEE ALSO
  251. *        ACreateMyListNode(), ADeleteMyListNode(), BAllocmem(), EnqueueLIFO()
  252. *
  253. ******************************************************************************
  254. *
  255. */
  256.  
  257. struct Node *ACreateMyListNodeNamedPri(struct List *header, ULONG length, STRPTR string, BYTE pri)
  258. {
  259. struct Node *pointer;
  260.     if(string)
  261.     {
  262.         pointer = (struct Node *)BAllocmem( length + strlen( string) + 1, MEMF_CLEAR | MEMF_PUBLIC);
  263.         if(pointer)
  264.         {
  265.             pointer->ln_Name = strcpy((char *) ((ULONG)pointer+length), string);
  266.             pointer->ln_Pri = pri;
  267.             EnqueueLIFO( header, pointer);
  268.         }
  269.     }
  270.     else
  271.     {
  272.         pointer = ACreateMyListNodePri( header, length, pri);
  273.     }
  274.     return(pointer);
  275. }
  276.  
  277.  
  278. /****i* patch.library/ACreateMyListNodePri ***************************************
  279. *
  280. *   NAME
  281. *        ACreateMyListNodePri -- Create and add a node with priority.
  282. *
  283. *   SYNOPSIS
  284. *        node = ACreateMyListNodePri( list, length, priority )
  285. *
  286. *        struct Node *ACreateMyListNodePri( struct List *, ULONG, BYTE );
  287. *
  288. *   FUNCTION
  289. *        Create a node structure of the given size and add it to
  290. *        the given list with the given priority.
  291. *        This node can be removed by a call to ADeleteMyListNode().
  292. *
  293. *   INPUTS
  294. *        list = pointer to a list structure or NULL for no action
  295. *        length = size of node in bytes
  296. *        priority = position at which the node is to be added to the list
  297. *
  298. *   RESULT
  299. *        node = pointer to the newly created node structure or NULL on failure
  300. *
  301. *   NOTES
  302. *
  303. *   BUGS
  304. *
  305. *   SEE ALSO
  306. *        ACreateMyListNode(), ADeleteMyListNode(), BAllocmem(), EnqueueLIFO()
  307. *
  308. ******************************************************************************
  309. *
  310. */
  311.  
  312. struct Node *ACreateMyListNodePri(struct List *header, ULONG length, BYTE pri)
  313. {
  314. struct Node *pointer = 0;
  315.     if(header)
  316.     {
  317.         pointer = (struct Node *)BAllocmem( length, MEMF_CLEAR | MEMF_PUBLIC);
  318.         if(pointer) 
  319.         {
  320.             pointer->ln_Pri = pri;
  321.             EnqueueLIFO( header, pointer);
  322.         }
  323.     }
  324.     return(pointer);
  325. }
  326.  
  327.  
  328. /****i* patch.library/AAllocmem ***************************************
  329. *
  330. *   NAME
  331. *        AAllocmem -- Allocate memory from the memory pool remembering
  332. *                     its size.
  333. *
  334. *   SYNOPSIS
  335. *        memory = AAllocmem( size, attributes, pool )
  336. *
  337. *        APTR AAllocmem( ULONG, ULONG, APTR );
  338. *
  339. *   FUNCTION
  340. *        Allocate memory from the global or (if it exists) from a local
  341. *        memory pool and remember its size.
  342. *        Deallocate this memory with AFreemem().
  343. *
  344. *   INPUTS
  345. *        size = number of bytes to allocate
  346. *        attributes = memory attributes (only required, if pool is NULL)
  347. *        pool = pointer to a memorypool as returned by CreatePool() or NULL, if
  348. *               memory should be allocated from the global memory.
  349. *
  350. *   RESULT
  351. *        memory = pointer to newly allocated memory block or NULL on failure
  352. *
  353. *   NOTES
  354. *
  355. *   BUGS
  356. *
  357. *   SEE ALSO
  358. *        Allocmem(), AllocVec(), AFreemem(), CreatePool()
  359. *
  360. ******************************************************************************
  361. *
  362. */
  363.  
  364.  
  365. APTR AAllocmem( ULONG size, ULONG attr, APTR pool)
  366. {
  367. ULONG *memory;
  368.  
  369.     size += 8;
  370.     if( pool)
  371.     {
  372.         memory = LibAllocPooled( pool, size);
  373.     }
  374.     else
  375.     {
  376.         memory = AllocMem( size, attr);
  377.     }
  378.  
  379.     if (memory)
  380.     {
  381.         *memory++ = size;
  382.         *memory++ = (ULONG)pool;
  383.     }
  384.     return( memory);
  385. }
  386.  
  387.  
  388. /****i* patch.library/AFreemem ***************************************
  389. *
  390. *   NAME
  391. *        AFreemem -- Free memory allocated from the memory pool.
  392. *
  393. *   SYNOPSIS
  394. *        AFreemem( memory )
  395. *
  396. *        AFreemem( APTR );
  397. *
  398. *   FUNCTION
  399. *        Free memory from the global or from a local
  400. *        memory pool.
  401. *        This memory must have been allocated with AAllocmem().
  402. *
  403. *   INPUTS
  404. *        memory = pointer to memoryblock
  405. *
  406. *   RESULT
  407. *
  408. *   NOTES
  409. *
  410. *   BUGS
  411. *
  412. *   SEE ALSO
  413. *        AAllocmem() 
  414. *
  415. ******************************************************************************
  416. *
  417. */
  418.  
  419. void AFreemem( APTR memory)
  420. {
  421. ULONG *mem;
  422.     if( memory)
  423.     {
  424.         mem = (ULONG *)memory - 2;
  425.         if (mem[1])
  426.             LibFreePooled((APTR) mem[1], mem, mem[0]);
  427.         else
  428.             FreeMem( mem, mem[0]);
  429.     }
  430. }
  431.  
  432.  
  433. /****i* patch.library/MyDelay ***************************************
  434. *
  435. *   NAME
  436. *        MyDelay -- Delay a task for a number of ticks.
  437. *
  438. *   SYNOPSIS
  439. *        MyDelay( ticks )
  440. *
  441. *        MyDelay( ULONG );
  442. *
  443. *   FUNCTION
  444. *        Put a task a number of ticks (1/50 seconds) to sleep.
  445. *
  446. *   INPUTS
  447. *        ticks = number of ticks (1/50 seconds) to wait
  448. *
  449. *   RESULT
  450. *
  451. *   NOTES
  452. *        This function has been written as it is unclear wether
  453. *        dos.library/Delay() may be called from tasks or not.
  454. *
  455. *   BUGS
  456. *        Number of ticks is restricted to about a minute
  457. *
  458. *   SEE ALSO
  459. *        dos.library/Delay()
  460. *
  461. ******************************************************************************
  462. *
  463. */
  464.  
  465. void MyDelay( LONG time)
  466. {
  467. struct MsgPort *msgport;
  468. struct IORequest *iorequest;
  469.  
  470.     if( msgport = CreateMsgPort())
  471.     {
  472.         if( iorequest = CreateExtIO( msgport, sizeof(struct timerequest)))
  473.         {
  474.             if( !OpenDevice("timer.device", UNIT_VBLANK, iorequest, 0L))
  475.             {
  476.                 ((struct timerequest *)iorequest)->tr_time.tv_secs = 0;
  477.                 ((struct timerequest *)iorequest)->tr_time.tv_micro = time * 20000;
  478.                 ((struct timerequest *)iorequest)->tr_node.io_Command = TR_ADDREQUEST;
  479.  
  480.                 DoIO( iorequest);
  481.  
  482.                 CloseDevice( iorequest);
  483.             }
  484.             DeleteExtIO( iorequest);
  485.         }
  486.         DeleteMsgPort(msgport);
  487.     }
  488. }
  489.  
  490. /****i* patch.library/FindNameNoCase ***************************************
  491. *
  492. *   NAME
  493. *        FindNameNoCase -- Search an exec-list not case-sensitive.
  494. *
  495. *   SYNOPSIS
  496. *        node = FindNameNoCase( list, string )
  497. *
  498. *        struct Node *FindNameNoCase( struct List *, STRPTR );
  499. *
  500. *   FUNCTION
  501. *        Search an exec-list not case-sensitive.
  502. *
  503. *   INPUTS
  504. *        list = pointer to List structure to search or NULL for no action
  505. *        string = C-String or NULL for no action.
  506. *
  507. *   RESULT
  508. *        node = pointer to node structure or NULL, if not found
  509. *
  510. *   NOTES
  511. *
  512. *   BUGS
  513. *
  514. *   SEE ALSO
  515. *        exec.library/FindName()
  516. *
  517. ******************************************************************************
  518. *
  519. */
  520.  
  521. struct Node *FindNameNoCase( struct List *header, STRPTR name)
  522. {
  523. struct Node *pointer = NULL;
  524.  
  525.     if( (header) && (name))
  526.     {
  527.         for( pointer = header->lh_Head;
  528.              pointer->ln_Succ;
  529.              pointer = pointer->ln_Succ)
  530.         {
  531.             if (stricmp( pointer->ln_Name, name) == 0L)
  532.                 break;
  533.         }
  534.     }
  535.     return( pointer);
  536. }
  537.  
  538.  
  539. /****i* patch.library/FindType ***************************************
  540. *
  541. *   NAME
  542. *        FindType -- Search an exec-list for a node of the given type.
  543. *
  544. *   SYNOPSIS
  545. *        node = FindType( list, type )
  546. *
  547. *        struct Node *FindType( struct List *, UBYTE );
  548. *
  549. *   FUNCTION
  550. *        Search an exec-list fo a node of the given type.
  551. *
  552. *   INPUTS
  553. *        list = pointer to List structure to search
  554. *        type = Type of node to search for.
  555. *
  556. *   RESULT
  557. *        node = pointer to node structure or NULL, if not found
  558. *
  559. *   NOTES
  560. *
  561. *   BUGS
  562. *
  563. *   SEE ALSO
  564. *
  565. ******************************************************************************
  566. *
  567. */
  568.  
  569.  
  570. struct Node *FindType( struct List *header,  UBYTE type)
  571. {
  572. struct Node *pointer;
  573.     for (pointer = (struct Node *)header->lh_Head;
  574.          pointer->ln_Succ;
  575.          pointer = (struct Node *)pointer->ln_Succ)
  576.     {
  577.         if( pointer->ln_Type == type) return( pointer);
  578.     }
  579.     return( NULL);
  580. }
  581.  
  582.  
  583. /****i* patch.library/GetListNodeHeader ***************************************
  584. *
  585. *   NAME
  586. *        GetListNodeHeader -- Get a List structure to a given node.
  587. *
  588. *   SYNOPSIS
  589. *        list = GetListNodeHeader( node )
  590. *
  591. *        struct List *FindType( struct Node * );
  592. *
  593. *   FUNCTION
  594. *        Get a pointer to the List structure of a given node.
  595. *
  596. *   INPUTS
  597. *        node = pointer to a Node structure
  598. *
  599. *   RESULT
  600. *        list = pointer to List structure
  601. *
  602. *   NOTES
  603. *        The node MUST belong to a List or everything might happen.
  604. *
  605. *   BUGS
  606. *
  607. *   SEE ALSO
  608. *
  609. ******************************************************************************
  610. *
  611. */
  612.  
  613. struct List *GetListNodeHeader( struct Node *pointer)
  614. {
  615.     for(;(pointer->ln_Succ);pointer = pointer->ln_Succ);
  616.     pointer = (struct Node *)(((ULONG *)pointer) - 1);
  617.     return( (struct List *)pointer);
  618. }
  619.  
  620.  
  621. /****i* patch.library/EnqueueLIFO ***************************************
  622. *
  623. *   NAME
  624. *        EnqueueLIFO -- Insert nodes in front of the first node
  625. *                       with the same priority
  626. *
  627. *   SYNOPSIS
  628. *        EnqueueLIFO( list, node )
  629. *
  630. *        EnqueueLIFO( struct List *, struct Node * );
  631. *
  632. *   FUNCTION
  633. *        Insert a node in front of the first node with the same priority
  634. *        (Last in, First out - style)
  635. *
  636. *   INPUTS
  637. *        list = pointer to List structure or NULL for no action
  638. *        node = pointer to Node structure or NULL for no action
  639. *
  640. *   RESULT
  641. *
  642. *   NOTES
  643. *       exec.library/Enqueue() works in FIFO - style.
  644. *
  645. *   BUGS
  646. *
  647. *   SEE ALSO
  648. *       exec.library/Enqueue()
  649. *
  650. ******************************************************************************
  651. *
  652. */
  653.  
  654.  
  655. void EnqueueLIFO( struct List *header, struct Node *newnode)
  656. {
  657. struct Node *pointer;
  658.     if( (header) && (newnode))
  659.     {
  660.         for (pointer = (struct Node *)header->lh_Head;
  661.              pointer->ln_Succ;
  662.                pointer = (struct Node *)pointer->ln_Succ)
  663.         {
  664.             if( pointer->ln_Succ->ln_Succ == NULL) break;
  665.             if( newnode->ln_Pri >= pointer->ln_Succ->ln_Pri) break;
  666.         }
  667.         if( header == (struct List *)pointer)
  668.         {
  669.             AddHead( header, newnode);
  670.         }
  671.         else
  672.         {
  673.             Insert( header, newnode, pointer);
  674.         }
  675.     }
  676. }
  677.  
  678. /****i* patch.library/SetJMPInstr ***************************************
  679. *
  680. *   NAME
  681. *        SetJMPInstr -- Modify a jump instruction
  682. *
  683. *   SYNOPSIS
  684. *        SetJMPInstr( memory, destination )
  685. *
  686. *        SetJMPInstr( UBYTE *, APTR );
  687. *
  688. *   FUNCTION
  689. *        Modify a (68K) jump instruction at a given location in memory to
  690. *        point to a new adress (destination).
  691. *
  692. *   INPUTS
  693. *        memory = memory location, where to place the instruction or
  694. *                 NULL for no action
  695. *        destination = memory location, to which the jump instruction is set
  696. *
  697. *   RESULT
  698. *
  699. *   NOTES
  700. *        On processors with cache this function must be enclosed by 
  701. *        disable(), FlushCache(), Enable().
  702. *        This function has been introduced to make patch.library
  703. *        portable.
  704. *
  705. *   BUGS
  706. *
  707. *   SEE ALSO
  708. *
  709. ******************************************************************************
  710. *
  711. */
  712.  
  713.  
  714. void SetJMPInstr( UBYTE *memptr, APTR destination)
  715. {
  716.     if( memptr)
  717.     {
  718.         *((UWORD *)memptr) = INSTR_JMP;
  719.         memptr += 2;
  720.         *((ULONG *)memptr) = (ULONG)destination;
  721.     }
  722. }
  723. /****i* patch.library/SetJSRInstr ***************************************
  724. *
  725. *   NAME
  726. *        SetJSRInstr -- Modify a jump-subroutine instruction
  727. *
  728. *   SYNOPSIS
  729. *        SetJSRInstr( memory, destination )
  730. *
  731. *        SetJSRInstr( UBYTE *, APTR );
  732. *
  733. *   FUNCTION
  734. *        Modify a (68K) jump-subroutine instruction at a given location
  735. *        in memory to point to a new adress (destination).
  736. *
  737. *   INPUTS
  738. *        memory = memory location, where to place the instruction or
  739. *                 NULL for no action
  740. *        destination = memory location, to which the jsr instruction is set
  741. *
  742. *   RESULT
  743. *
  744. *   NOTES
  745. *        On processors with cache this function must be enclosed by 
  746. *        disable(), FlushCache(), Enable().
  747. *        This function has been introduced to make patch.library
  748. *        portable.
  749. *
  750. *   BUGS
  751. *
  752. *   SEE ALSO
  753. *
  754. ******************************************************************************
  755. *
  756. */
  757.  
  758.  
  759. void SetJSRInstr( UBYTE *memptr, APTR destination)
  760. {
  761.     if( memptr)
  762.     {
  763.         *((UWORD *)memptr) = INSTR_JSR;
  764.         memptr += 2;
  765.         *((ULONG *)memptr) = (ULONG)destination;
  766.     }
  767. }
  768.